Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Turn eager normalization errors to delayed errors #82039

Closed
wants to merge 1 commit into from

Conversation

estebank
Copy link
Contributor

When normalizing unions with fields coming from associated types that
don't satisfy trait bounds, avoid ICEing by using delay_span_bug()
instead of bug!().

Fix #81199.

@rust-highfive
Copy link
Collaborator

r? @lcnr

(rust-highfive has picked a reviewer for you, use r? to override)

@rust-highfive rust-highfive added the S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. label Feb 12, 2021
}
}
_ => {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is this actually reachable? Do we have a test case where hir::ItemKind::Union ends up as ty::Error?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also curious about this. Was this getting hit? If not, can you revert?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

IIRC, I added this because it is reached after removing the other ICE.

@@ -40,7 +41,13 @@ fn normalize_generic_arg_after_erasing_regions<'tcx>(
debug_assert!(!erased.needs_infer(), "{:?}", erased);
erased
}
Err(NoSolution) => bug!("could not fully normalize `{:?}`", value),
Copy link
Contributor

@lcnr lcnr Feb 13, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this bug is quite valuable and helped us catch some bugs with const generics, so I would really like to keep it that way.

We pretty much only emit a bug here if the type is not well formed, and I think normalize_erasing_regions should only be used on types that are well formed (even if there is another error).

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think having delay_span_bug here should be fine. This mimics bug with -Ztreat-err-as-bug right?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We get there with const evaluatable bounds when emitting errors, but these errors should be silent when encountered during selection, so just always causing an ICE here is preferable for me.

We shouldn't hit this, even after having a compilation error. Having a delay_span_bug here hides other bugs in the compiler.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We get there with const evaluatable bounds when emitting errors, but these errors should be silent when encountered during selection, so just always causing an ICE here is preferable for me.

I'm not sure I follow. Could you rephrase your position? It reads to me like

  • We get there with const evaluatable bounds when emitting errors
  • these errors should be silent when encountered during selection
  • always causing an ICE here is preferable

means

  • when we emit errors with const evaluatable bounds we get here
  • trait selection should silence this errors
  • we should always ICE when we hit these

which to me is saying two different things?


Would it be reasonable to only delay_span_bug on stable/beta and make it bug! in nightly?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think what @lcnr means is that the error we get here would be silenced by trait selection, but we don't want that and should ICE.

I would be extremely wary of having different behavior on stable vs nightly.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We get there with const evaluatable bounds when emitting errors,

it is an implementation error for const evaluatable bounds to reach this bug! and we still don't know all the places where this happens. Often when reaching this bug! compilation would fail anyways so a delay_span_bug would not trigger in these cases. That would mean that we would only get ICE here once they get triggered by const evaluatable bounds during selection (which then succeeds using a different candidate). This happens a lot less often though, so it would take us longer to find all of these cases. Does this make more sense this way?

.ty_adt_def()
.map_or(false, |adt_def| adt_def.is_manually_drop())
&& !field_ty
.is_copy_modulo_regions(self.tcx.at(DUMMY_SP), param_env)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this is the actual problem here. imo is_copy_modulo_regions doesn't make sense outside of codegen/mir building.

This is currently a stability hole as the following compiles:

#[derive(Clone)]
struct Bar<'a>(&'a ());

impl Copy for Bar<'static> {}

union Foo<'a> {
    field: u32,
    other_field: Bar<'a>,
}

For some reason we also explicitly require types to be copy when initializing a union, so the following does error:

fn test<'a>(q: &'a ()) {
    let bar = Bar(&q);
    let foo: Foo<'a> = Foo {
        other_field: bar,
    };
}

https://play.rust-lang.org/?version=nightly&mode=debug&edition=2018&gist=45ea9990bc47e6066abeec085a372b85


Does using the following also fix this ICE?

let trait_ref = TraitRef::new(copy_def_id, tcx.intern_substs(&[field_ty.into()]));

let is_copy = tcx.infer_ctxt().enter(|infcx| {
    infcx.predicate_must_hold_considering_regions(Obligation::new(
        ObligationCause::dummy(),
        param_env,
        trait_ref.without_const().to_predicate(tcx),
    ))
});

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think this is the root issue, but I agree that this seems like a potential soundness hole. I would maybe just file an issue for followup.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think this is the root issue

My understanding is that the root issue is calling codegen_fulfill_obligations outside of codegen. I am a bit confused about why I said that is_copy_modulo_regions is the issue here when there's a call to normailize_erasing_regions right below it - as you've said in #82039 (comment). I personally prefer to "correctly" deal with regions in needs_drop and similar methods, even if that is a more complex change.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, I agree. We shouldn't be erasing regions in needs_drop and that is the more correct fix here.

@bors
Copy link
Contributor

bors commented Feb 17, 2021

☔ The latest upstream changes (presumably #81611) made this pull request unmergeable. Please resolve the merge conflicts.

@crlf0710 crlf0710 added S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. and removed S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. labels Mar 5, 2021
@JohnCSimon JohnCSimon added S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. and removed S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. labels Mar 22, 2021
@crlf0710 crlf0710 added S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. and removed S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. labels Apr 9, 2021
@JohnCSimon JohnCSimon added S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. and removed S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. labels Apr 26, 2021
@Dylan-DPC-zz
Copy link

@estebank this is waiting for you to reply to the review and resolve the conflicts

@bstrie bstrie added S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. and removed S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. labels May 12, 2021
@lcnr
Copy link
Contributor

lcnr commented May 24, 2021

I am not able to review any PRs in the near future. I don't think there is anything a reviewer has to do for this PR right now

r? @matthewjasper

@rust-highfive rust-highfive assigned matthewjasper and unassigned lcnr May 24, 2021
@crlf0710 crlf0710 added S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. and removed S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. labels Jun 11, 2021
@JohnCSimon
Copy link
Member

ping again from triage:
@estebank this is waiting for you to reply to the review and resolve the conflicts

@JohnCSimon JohnCSimon added S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. and removed S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. labels Jul 12, 2021
@camelid
Copy link
Member

camelid commented Jul 25, 2021

FYI, @jyn514 found a very small minimization in #87327 (comment) that may be useful as a test case:

union U {
    a: <Self as Iterator>::Item,
}

@crlf0710 crlf0710 added S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. and removed S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. labels Aug 14, 2021
@jackh726
Copy link
Member

r? @jackh726

Copy link
Member

@jackh726 jackh726 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A couple comments but this looks good enough to me that I'm good with merging

}
}
_ => {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also curious about this. Was this getting hit? If not, can you revert?

.ty_adt_def()
.map_or(false, |adt_def| adt_def.is_manually_drop())
&& !field_ty
.is_copy_modulo_regions(self.tcx.at(DUMMY_SP), param_env)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think this is the root issue, but I agree that this seems like a potential soundness hole. I would maybe just file an issue for followup.

&& !field_ty
.is_copy_modulo_regions(self.tcx.at(DUMMY_SP), param_env)
{
if field_ty.needs_drop(self.tcx, param_env) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So, under the presumption that we should only be calling normalize_erasing_regions on well-formed types, is the problem actually in needs_drop...?
Here:

let subst_ty = tcx.normalize_erasing_regions(

@@ -40,7 +41,13 @@ fn normalize_generic_arg_after_erasing_regions<'tcx>(
debug_assert!(!erased.needs_infer(), "{:?}", erased);
erased
}
Err(NoSolution) => bug!("could not fully normalize `{:?}`", value),
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think having delay_span_bug here should be fine. This mimics bug with -Ztreat-err-as-bug right?

When normalizing `union`s with fields coming from associated types that
don't satisfy trait bounds, avoid ICEing by using `delay_span_bug()`
instead of `bug!()`.

Fix rust-lang#81199.
@JohnCSimon JohnCSimon added S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. and removed S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. labels Sep 12, 2021
@JohnCSimon
Copy link
Member

triage:

jackh726 left a comment
A couple comments but this looks good enough to me that I'm good with merging

setting to waiting on review

@JohnCSimon JohnCSimon added S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. and removed S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. labels Sep 12, 2021
@jackh726
Copy link
Member

Okay after the discussion in this thread, particularly with @lcnr, I'm now of mixed minds about this PR. Let me explain my thought process.

First, as a bit of context to my thoughts, it's important to note that there are currently two real "ways" to normalize things: either through rustc_trait_selection::traits::project or rustc_trait_selection::traits::query::normalize (which under the hood uses the same machinery). These two entrypoints to normalize have different goals: the former is designed around the case of "try to normalize, if we can, we'll try later when we have more information; if there are required obligations for normalization, we can solve them later too" and the latter is "we must be able to normalize everything; if we can't it's an error. Furthermore, we must be able to prove all obligations." Unfortunately, normalize_erasing_regions bugs on Error. In the medium-to-long term, we should work to solidify the expected invariants here and eventually just unify these two entrypoints (but that's definitely not in scope for this PR at all).

The current expectation here is that everything can get normalized in normalize_erasing_regions; rather than making an exception for this one case, maybe we should take an alternative approach. Can we call query::normalize directly from needs_drop?

Another alternative is that the stability logic here isn't in the right place (should it be delayed until after we type check correctly?)

@camelid camelid added S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. and removed S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. labels Sep 18, 2021
@JohnCSimon JohnCSimon added S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. and removed S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. labels Oct 3, 2021
@JohnCSimon JohnCSimon added S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. and removed S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. labels Oct 19, 2021
@JohnCSimon JohnCSimon added S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. and removed S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. labels Nov 8, 2021
@jackh726
Copy link
Member

jackh726 commented Dec 4, 2021

The issue was fixed with #91462. Closing this.

@jackh726 jackh726 closed this Dec 4, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Normalizing <T as Trait>::AssocType in a union causes an ICE